package com.book.common.helper;

import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.NamedThreadLocal;
import org.springframework.stereotype.Component;

import java.util.Locale;
import java.util.Map;
import java.util.Optional;

/**
 * Description：国际化
 *
 * @Author： leo.xiong
 * @CreateDate： 2020/03/31 16:01
 * @Email： leo.xiong@suyun360.com
 * Version：1.0
 */
@Component
public class I18nHelper {
    private final static String COMM_BASE_PATH = "comm_";
    private final static String CORE_BASE_PATH = "core_";
    private final static String DEFAULT_BASE_NAME = "messages";
    private final static String DEFAULT_BASE_PATH = "i18n";
    private static Map<String, ResourceBundleMessageSource> BASE_NAME_SOURCE_MAP = Maps.newConcurrentMap();
    private ResourceBundleMessageSource messageSource;

    public I18nHelper() {
        messageSource = buildResourceBundleMessageSource(DEFAULT_BASE_NAME);
    }

    private ResourceBundleMessageSource buildResourceBundleMessageSource(String baseName) {
        ResourceBundleMessageSource baseNameMessageSource = new ResourceBundleMessageSource();
        baseNameMessageSource.setBasenames(new String[]{DEFAULT_BASE_PATH + "/" + COMM_BASE_PATH + baseName, COMM_BASE_PATH + baseName, DEFAULT_BASE_PATH + "/" + CORE_BASE_PATH + baseName, CORE_BASE_PATH + baseName, DEFAULT_BASE_PATH + "/" + baseName, baseName});
        BASE_NAME_SOURCE_MAP.put(baseName, baseNameMessageSource);
        return baseNameMessageSource;
    }

    /**
     * 存储当前线程的Locale
     */
    public static final ThreadLocal<Locale> LOCALE_THREAD_LOCAL = new NamedThreadLocal<>("International language");
    /**
     * 占位符
     */
    public static final String PLACEHOLDER = "%S";

    /**
     * 设置当前线程的语言，不设置，取当前系统默认语言
     *
     * @param language
     * @param country
     */
    public void setLocale(String language, String country) {
        if (StringUtils.isEmpty(language)) {
            LOCALE_THREAD_LOCAL.set(Locale.getDefault());
        } else if (StringUtils.isEmpty(country)) {
            String[] languageAndCountry = language.replace("-", "_").split("_");
            if (languageAndCountry.length > 1) {
                LOCALE_THREAD_LOCAL.set(new Locale(languageAndCountry[0], languageAndCountry[1]));
            } else {
                LOCALE_THREAD_LOCAL.set(new Locale(languageAndCountry[0], null));
            }
        } else {
            LOCALE_THREAD_LOCAL.set(new Locale(language, country));
        }
    }

    /**
     * 获取当前线程语言，如果已经设置，取设置的，否则，取默认语言，并且更新当前线程的语言信息
     */
    public Locale getLocale() {
        return getLocale(null, null);
    }

    /**
     * 获取当前线程语言，如果已经设置，取设置的，否则，取当前语言和国家的语言,并且更新当前线程的语言信息
     */
    public Locale getLocale(String language, String country) {
        if (LOCALE_THREAD_LOCAL.get() == null) {
            setLocale(language, country);
        }
        return LOCALE_THREAD_LOCAL.get();
    }

    /**
     * 移除当前语言
     */
    public void removeLocale() {
        LOCALE_THREAD_LOCAL.remove();
    }

    /**
     * 取默认配置文件的国际化语言
     *
     * @param key
     * @return
     */
    public String get(String key) {
        return this.getValue(null, key, null).replace(PLACEHOLDER, "");
    }

    /**
     * 存在占位符的数据处理
     *
     * @param key
     * @param placeholderValue
     * @return
     */
    public String get(String key, String placeholderValue) {
        return this.getValue(null, key, null).replace(PLACEHOLDER, " " + placeholderValue + " ");
    }

    public String getString(String key, String defaultValue) {
        return getValue(null, key, defaultValue).replace(PLACEHOLDER, "");
    }

    public String getString(String key, String placeholderValue, String defaultValue) {
        return getValue(null, key, defaultValue).replace(PLACEHOLDER, " " + placeholderValue + " ");
    }

    /**
     * 获取value的国际化语言，默认取配置文件的，
     * 配置文件取不到则取谷歌翻译的，如果还取不到，
     * 则判断默认值是否为空，不为空，取默认值，
     * 否则取传入的值
     *
     * @param baseName
     * @param key
     * @return
     */
    public String getValue(String baseName, String key, String defaultValue) {
        if (StringUtils.isEmpty(key)) {
            return "";
        }
        baseName = Optional.ofNullable(baseName).orElse(DEFAULT_BASE_NAME);
        try {
            return getMessage(baseName, key, getLocale());
        } catch (NoSuchMessageException e) {
            return StringUtils.isEmpty(defaultValue) ? key : defaultValue;
        }
    }

    /**
     * 多线程情况加锁
     *
     * @param targetBaseName
     * @param key
     * @param targetLocale
     */
    private String getMessage(String targetBaseName, String key, Locale targetLocale) throws NoSuchMessageException {
        if (StringUtils.isEmpty(targetBaseName)) {
            return messageSource.getMessage(key, null, targetLocale);
        }
        ResourceBundleMessageSource targetMessageSource = BASE_NAME_SOURCE_MAP.get(targetBaseName);
        if (targetMessageSource == null) {
            targetMessageSource = buildResourceBundleMessageSource(targetBaseName);
        }
        return targetMessageSource.getMessage(key, null, targetLocale);
    }
}
